package tu.j2ee.tasktracker.controller;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import org.joda.time.format.DateTimeFormat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.roo.addon.web.mvc.controller.scaffold.RooWebScaffold;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.util.UriUtils;
import org.springframework.web.util.WebUtils;
import tu.j2ee.tasktracker.dao.CommentDAO;
import tu.j2ee.tasktracker.dao.CustomUserDAO;
import tu.j2ee.tasktracker.dao.ProjectDAO;
import tu.j2ee.tasktracker.dao.TaskChangeDAO;
import tu.j2ee.tasktracker.dao.TaskDAO;
import tu.j2ee.tasktracker.domain.CustomUser;
import tu.j2ee.tasktracker.domain.Task;
import tu.j2ee.tasktracker.domain.TaskChange;
import tu.j2ee.tasktracker.domain.TaskStatus;

@RequestMapping("/tasks")
@Controller
@RooWebScaffold(path = "tasks", formBackingObject = Task.class)
public class TaskController {

	@Autowired
    TaskDAO taskDAO;

	@Autowired
    CommentDAO commentDAO;

	@Autowired
    CustomUserDAO customUserDAO;

	@Autowired
    ProjectDAO projectDAO;
	
	@Autowired
	TaskChangeDAO taskChangeDAO;

	@RequestMapping(value= "/my", method = RequestMethod.GET, produces = "text/html")
	public String myTasks(@RequestParam(value="forProject", required = false)Long forProject, Model uiModel) {
        //all projects for the select
		uiModel.addAttribute("projects", projectDAO.findAll());
		//current project selected
        uiModel.addAttribute("forProject", forProject);
		
        String username = SecurityContextHolder.getContext().getAuthentication().getName();
		CustomUser user = customUserDAO.findByUsername(username);
		List<Task> myTasks = null;
		if (forProject != null) {
			myTasks = taskDAO.findByAssignedUserIdAndProjectId(user.getId(), forProject);
		}else {
			myTasks = taskDAO.findByAssignedUserId(user.getId());
		}
		//all tasks for the current user
		uiModel.addAttribute("tasks", myTasks);
		
		return "tasks/list";
	}
	
	
	@RequestMapping(method = RequestMethod.POST, produces = "text/html")
    public String create(@Valid Task task, BindingResult bindingResult, Model uiModel, HttpServletRequest httpServletRequest) {
        if (bindingResult.hasErrors()) {
            populateEditForm(uiModel, task);
            return "tasks/create";
        }
        uiModel.asMap().clear();
        taskDAO.save(task);
        return "redirect:/tasks/" + encodeUrlPathSegment(task.getId().toString(), httpServletRequest);
    }

	@RequestMapping(params = "form", produces = "text/html")
    public String createForm(Model uiModel) {
        populateEditForm(uiModel, new Task());
        List<String[]> dependencies = new ArrayList<String[]>();
        if (projectDAO.count() == 0) {
            dependencies.add(new String[] { "project", "projects" });
        }
        uiModel.addAttribute("dependencies", dependencies);
        return "tasks/create";
    }

	@RequestMapping(value = "/{id}", produces = "text/html")
    public String show(@PathVariable("id") Long id, Model uiModel) {
        addDateTimeFormatPatterns(uiModel);
        uiModel.addAttribute("task", taskDAO.findOne(id));
        uiModel.addAttribute("itemId", id);
        uiModel.addAttribute("comments", commentDAO.findByTaskId(id));
        return "tasks/show";
    }

	@RequestMapping(produces = "text/html")
    public String list(@RequestParam(value="forProject", required = false)Long forProject, Model uiModel) {
        //all projects for the select
		uiModel.addAttribute("projects", projectDAO.findAll());
		//current project selected
        uiModel.addAttribute("forProject", forProject);
        if(forProject != null){
        	List<Task> findByProjectId = taskDAO.findByProjectId(forProject);
        	uiModel.addAttribute("tasks", findByProjectId);
        }else {
            uiModel.addAttribute("tasks", taskDAO.findAll());
		}
        	
        addDateTimeFormatPatterns(uiModel);
        return "tasks/list";
    }

	@RequestMapping(method = RequestMethod.PUT, produces = "text/html")
    public String update(@Valid Task task, BindingResult bindingResult, Model uiModel, HttpServletRequest httpServletRequest) {
        if (bindingResult.hasErrors()) {
            populateEditForm(uiModel, task);
            return "tasks/update";
        }
        uiModel.asMap().clear();
        taskDAO.save(task);
        taskChanged(task);
        return "redirect:/tasks/" + encodeUrlPathSegment(task.getId().toString(), httpServletRequest);
    }
	
	private void taskChanged(Task task) {
		TaskChange changeTask = new TaskChange();
		changeTask.setAssignedUser(task.getAssignedUser());
		changeTask.setDescription(task.getDescription());
		changeTask.setEstimatedDate(task.getEstimatedDate());
		changeTask.setProject(task.getProject());
		changeTask.setStatus(task.getStatus());
		changeTask.setTask(task);
		changeTask.setTitle(task.getTitle());
		
		taskChangeDAO.save(changeTask);
	}

	@RequestMapping(value = "/{id}", params = "form", produces = "text/html")
    public String updateForm(@PathVariable("id") Long id, Model uiModel) {
        populateEditForm(uiModel, taskDAO.findOne(id));
        return "tasks/update";
    }

	@RequestMapping(value = "/{id}", method = RequestMethod.DELETE, produces = "text/html")
    public String delete(@PathVariable("id") Long id, @RequestParam(value = "page", required = false) Integer page, @RequestParam(value = "size", required = false) Integer size, Model uiModel) {
        Task task = taskDAO.findOne(id);
        taskDAO.delete(task);
        uiModel.asMap().clear();
        uiModel.addAttribute("page", (page == null) ? "1" : page.toString());
        uiModel.addAttribute("size", (size == null) ? "10" : size.toString());
        return "redirect:/tasks";
    }

	void addDateTimeFormatPatterns(Model uiModel) {
        uiModel.addAttribute("task_estimateddate_date_format", DateTimeFormat.patternForStyle("M-", LocaleContextHolder.getLocale()));
    }

	void populateEditForm(Model uiModel, Task task) {
        uiModel.addAttribute("task", task);
        addDateTimeFormatPatterns(uiModel);
        uiModel.addAttribute("comments", commentDAO.findAll());
        uiModel.addAttribute("customusers", customUserDAO.findAll());
        uiModel.addAttribute("projects", projectDAO.findAll());
        uiModel.addAttribute("taskstatuses", Arrays.asList(TaskStatus.values()));
    }

	String encodeUrlPathSegment(String pathSegment, HttpServletRequest httpServletRequest) {
        String enc = httpServletRequest.getCharacterEncoding();
        if (enc == null) {
            enc = WebUtils.DEFAULT_CHARACTER_ENCODING;
        }
        try {
            pathSegment = UriUtils.encodePathSegment(pathSegment, enc);
        } catch (UnsupportedEncodingException uee) {}
        return pathSegment;
    }
}
